(function (window) {
    Map.prototype.mapStage = null;
    Map.prototype.mapContentmanager = null;
    function Map(stage, contentManager) {
        this.mapStage = stage;
        this.mapContentManager = contentManager;
    }

    Map.prototype.Character = null;
    Map.prototype.wires = [];
    Map.prototype.switches = [];
    Map.prototype.paths = [];
    Map.prototype.resistors = [];
    Map.prototype.currents = [];
    Map.prototype.goalDevice = null;
    Map.prototype.battery = [];
    Map.prototype.background = null;
    Map.prototype.timeStarted = 0;
    Map.prototype.timeElapsed = 0;
    Map.prototype.threeStars = 0;
    Map.prototype.twoStars = 0;
    Map.prototype.current = 0;
    Map.prototype.voltage = 0;
    Map.prototype.resistance = 0;
    Map.prototype.max = 0;

    Map.prototype.Dispose = function () {
        this.Character.Dispose();
        Map.prototype.wires = [];
        Map.prototype.resistors = [];
        Map.prototype.goalDevice = null;
        Map.prototype.battery = [];
        Map.prototype.max = 0;
        Map.prototype.background = null;
        Map.prototype.timeElapsed = 0;
        Map.prototype.timeStarted = 0;
        Map.prototype.switches = [];
        Map.prototype.paths = [];
        Map.prototype.currents = [];
        Map.prototype.threeStars = 0;
        Map.prototype.twoStars = 0;
        Map.prototype.current = 0;
        Map.prototype.voltage = 0;
        Map.prototype.resistance = 0;
        Ticker.removeAllListeners();
        this.mapStage.removeAllChildren();
        this.mapStage.update();

    }

    Map.prototype.loadLevel = function (level) {

        var sw = level.map.layer[1].switches;
        var w = level.map.layer[1].wires;
        var p = level.map.layer[1].paths;
        var b = level.map.layer[1].batteries;
        var r = level.map.layer[1].resistors;
        var gD = level.map.layer[1].goal_device;
        var c = level.map.layer[1].ohm_nohm;
        var bg = level.map.layer[0].bgImage;
        var three = level.map.layer[0].three;
        var two = level.map.layer[0].two;
        var par = level.map.layer[1].parallel;

        this.goalDevice = this.loadGoalDevice(gD);
        this.Character = this.loadCharacter(c);
        this.background = this.loadBackground(bg);
        Map.prototype.threeStars = three;
        Map.prototype.twoStars = two;

        for (var i = 0; i < sw.length; i++) {
            this.switches[i] = (this.loadSwitch(sw[i]));
        }
        for (var i = 0; i < w.length; i++) {
            this.wires[i] = (this.loadWire(w[i]));
        }
        if (par != null) {
            for (var i = 0; i < par.length; i++) {
                for (var j = 0; j < par[i].wires.length; j++)
                    this.wires.push(this.loadWire(par[i].wires[j]));
            }
        }
        for (var i = 0; i < p.length; i++) {
            this.paths[i] = (this.loadPath(p[i]));
        }
        for (var i = 0; i < b.length; i++) {
            this.battery[i] = this.loadBattery(b[i]);
        }

        for (var i = 0; i < r.length; i++) {
            this.resistors[i] = this.loadResistor(r[i]);
        }

    }

    Map.prototype.loadBackground = function (bg) {
        if (bg) {
            var img = this.mapContentManager.GetImageByName(bg);
            return new Bitmap(img);
        } else {
            return null;
        }
    }

    Map.prototype.loadResistor = function (r) {
        var resistor = new Resistor(this.mapContentManager.imgResistor, r.resistance, r.onWire, r.x, r.y, r.onParallel, r.parallel);

        return resistor;
    }

    Map.prototype.loadWire = function (w) {
        var wire = new Wire(w.fromX, w.fromY, w.toX, w.toY, w.stroke);
        return wire;
    }

    Map.prototype.loadSwitch = function (sw) {
        var eswitch = new Switch(sw.x, sw.y, sw.stroke, sw.status, sw.onWire);
        return eswitch;
    }

    Map.prototype.loadPath = function (p) {
        var path = new Path(p.wires, p.battery, p.goal_device);
        return path;
    }

    Map.prototype.loadBattery = function (b) {
        var battery = new Battery(b.x, b.y, b.voltage, this.mapContentManager.imgBattery);

        return battery;
    }

    Map.prototype.loadCharacter = function (c) {
        var character = new Character(this.mapContentManager.imgCharacter, c.x, c.y);
        return character;
    }

    Map.prototype.loadGoalDevice = function (gd) {
        var goal = new GoalDevice(this.mapContentManager.imgTV, gd.resistance, gd.x, gd.y, gd.voltage);

        return goal;
    }

    Map.prototype.startLevel = function () {
        this.mapStage.addChild(this.background);

        for (var i = 0; i < this.switches.length; i++) {
            this.mapStage.addChild(this.switches[i]);
            this.switches[i].onClick = this.switchClosed;
        }
        for (var i = 0; i < this.wires.length; i++) {
            this.mapStage.addChild(this.wires[i]);
        }
        for (var i = 0; i < this.paths.length; i++) {
            this.mapStage.addChild(this.paths[i]);
        }
        for (var i = 0; i < this.battery.length; i++) {
            this.mapStage.addChild(this.battery[i]);
        }
        for (var i = 0; i < this.resistors.length; i++) {
            this.mapStage.addChild(this.resistors[i]);
        }
        this.mapStage.addChild(this.Character);
        for (var i = 0; i < this.battery.length; i++) {
            var voltageLabel = new Text(this.battery[i].voltage + " Volts", "20px Fredoka One", "#000");
            voltageLabel.x = this.battery[i].x;
            voltageLabel.y = this.battery[i].y - 5;
            this.mapStage.addChild(voltageLabel);
        }
        for (var i = 0; i < this.resistors.length; i++) {
            var resistanceLabel = new Text(this.resistors[i].resistance + " Ohms", "20px Fredoka One", "#000");
            resistanceLabel.x = this.resistors[i].x - 8;
            resistanceLabel.y = this.resistors[i].y - 30;
            this.mapStage.addChild(resistanceLabel);
        }

        this.mapStage.addChild(this.goalDevice);
        this.mapStage.addChild(this.Character);

        this.mapStage.update();

        Map.prototype.timeStarted = getTime();

        Ticker.addListener(this);
        Ticker.setFPS(60);
    }



    Map.prototype.tick = function () {
        this.Character.Update();
        for (var i = 0; i < this.resistors.length; i++) {
            var resistor = this.resistors[i];

            resistor.update();
        }

        this.mapStage.update();
    }

    var self = this;
    Map.prototype.switchClosed = function (e) {

        // Either close or open the switch based on previous condition
        console.log(e);
        var clickedSwitch = e.target;
        if (clickedSwitch.status == "On") {
            clickedSwitch.status = "Off";
            clickedSwitch.openSwitch(clickedSwitch);
        } else {
            clickedSwitch.status = "On";
            clickedSwitch.closeSwitch(clickedSwitch);
        }


        // Check if a path has been created by checking all switches in every path
        for (var i = 0; i < Map.prototype.paths.length; i++) {
            // Get all switches in a path
            var pathSwitches = Map.prototype.getSwitches(Map.prototype.paths[i]);
            console.log(pathSwitches);
            var switchesClosed = true;
            for (var j = 0; j < pathSwitches.length; j++) {
                if (pathSwitches[j].status == "Off") {
                    switchesClosed = false;
                    break;
                }
            }

            // If all switches are closed
            if (switchesClosed) {
                //alert("A path has been formed! Path : " + i)
                var maxCurrent = Map.prototype.getMapMaximumCurrent();
                // Get current for the closed path
                var pathCurrent = Map.prototype.getPathCurrent(Map.prototype.paths[i]);

                // Set Animation speed based on current 
                var animationSpeed = (pathCurrent / maxCurrent) * 10;
                // ANimate movement
                Map.prototype.animateCharacter(self.stage.children[self.stage.children.length - 1], Map.prototype.paths[i], animationSpeed);
                self.map.goalDevice.gotoAndPlay("turnon");
                // Get time 
                Map.prototype.timeElapsed = getTime() - Map.prototype.timeStarted;
                // alert("You completed this level in " + Map.prototype.timeElapsed / 1000 + " seconds");
            } else {
                //alert("You have to close more switches to form a path");
            }
        }

    }

    Map.prototype.getSwitches = function (path) {
        var wires = path.wires;
        var temp_switches = [];
        for (var i = 0; i < wires.length; i++) {
            if (wires[i].type == "parallel")
                continue;
            for (var j = 0; j < this.switches.length; j++) {
                if (this.switches[j].onWire == wires[i].id) {
                    temp_switches.push(this.switches[j]);
                }
            }
        }
        return temp_switches;
    }


    var self = this;
    Map.prototype.getPathCurrent = function (path) {
        var wires = path.wires;
        var resistance = 0;
        for (var i = 0; i < wires.length; i++) {
            if (wires[i].type == "parallel")
                continue;
            for (var j = 0; j < this.resistors.length; j++) {
                if (this.resistors[j].onWire == wires[i].id) {
                    resistance += this.resistors[j].resistance;
                }
            }
        }
        for (var i = 0; i < wires.length; i++) {
            if (wires[i].type == "series")
                continue;
            var parallelResistance = [];
            for (var j = 0; j < this.resistors.length; j++) {
                if (this.resistors[j].parallel) {
                    if (this.resistors[j].onParallel == wires[i].id) {
                        parallelResistance.push(this.resistors[j].resistance);
                    }
                }
            }
            if (parallelResistance.length == 0)
                continue;
            var numer = 1;
            var denom = 0;
            for (var j = 0; j < parallelResistance.length; j++) {
                numer *= parallelResistance[j];
                denom += parallelResistance[j];
            }
            resistance += numer / denom;
        }

        console.log(self.map.GoalDevice);
        var batteryVoltage = this.battery[path.battery].voltage;
        var deviceVoltage = self.stage.children[self.stage.children.length - 2].voltage;
        console.log(self.stage.children[self.stage.children.length - 2].voltage);
        var voltage = batteryVoltage;
        var current = voltage / resistance;

        Map.prototype.current = current;
        Map.prototype.voltage = voltage;
        Map.prototype.resistance = resistance;
        console.log(voltage);
        console.log(resistance);
        console.log("Current " + current.toString());
        return current;
    }

    Map.prototype.getMapMaximumCurrent = function () {
        var maxCurrent = 0;
        for (var i = 0; i < this.paths.length; i++) {
            Map.prototype.currents[i] = this.getPathCurrent(this.paths[i]);
            if (maxCurrent < this.getPathCurrent(this.paths[i])) {
                maxCurrent = this.getPathCurrent(this.paths[i]);
                Map.prototype.max = maxCurrent;
            }
        }

        Map.prototype.currents.sort();
        Map.prototype.currents.reverse();
        return maxCurrent;
    }

    Map.prototype.animateCharacter = function (character, path, speed) {
        var wires = path.wires;
        character.totalWires = wires.length;
        character.x = Map.prototype.wires[wires[0].id].from[0];
        character.y = Map.prototype.wires[wires[0].id].from[1];
        self.stage.update();

        for (var i = 0; i < wires.length; i++) {
            if(wires[i].type == "parallel")
                continue;
            var startX = Map.prototype.wires[wires[i].id].from[0];
            var startY = Map.prototype.wires[wires[i].id].from[1];
            var endX = Map.prototype.wires[wires[i].id].to[0];
            var endY = Map.prototype.wires[wires[i].id].to[1];

            self.stage.update();
            if (startY === endY) {
                character.path.push(endX);
                character.xVels.push(speed);
                character.yVels.push(0);
            } else if (startX === endX) {
                if (endY > startY) {
                    character.path.push(endY);
                    character.xVels.push(0);
                    character.yVels.push(speed);
                } else {
                    character.path.push(endY);
                    character.xVels.push(0);
                    character.yVels.push(-1 * speed);
                }
            }
        }
        var endX = Map.prototype.wires[wires[wires.length - 1].id].to[0];
        var endY = Map.prototype.wires[wires[wires.length - 1].id].to[1];
        var goalDeviceX = self.map.goalDevice.x;
        var goalDeviceY = self.map.goalDevice.y;
        character.path.push(goalDeviceX);
        character.xVels.push(speed);
        character.yVels.push(0);
        Map.prototype.timeStarted = getTime();
    }

    function getTime() {
        var day = new Date();
        return day.getTime();
    }

    window.Map = Map;
} (window));